package facade.base;

import cache.CacheHelper;
import ext.Func;
import facade.PageResult;
import facade.open.KeyMessage;
import facade.open.response.CorpResponse;
import helper.BeanHelper;
import helper.GlobalConfig;
import helper.GlobalConfigKeys;
import models.base.AdminUser;
import models.base.Corp;
import models.base.EntityProp;
import models.enums.LicenseEdition;
import models.enums.OpenIdSource;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.EnumUtils;
import org.slf4j.LoggerFactory;
import play.Logger;
import play.Play;
import play.data.validation.Required;
import play.data.validation.Valid;
import play.mvc.Http;
import play.mvc.Scope;
import util.DateHelper;
import util.common.DateUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 公司facade.
 */
public class CorpFacade {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CorpFacade.class);

    public static Corp createWithApp(String name, int validDays) {
        Corp corp = Corp.createDefaultTrialCorp(name, validDays);
        corp.save();
        // 生成一个默认OfficeArea
        //OfficeArea.create(corp, Messages.get("office-areas.default-name"));

        return corp;
    }

    public static Corp createTrialCorp(String name, int validDays) {

        Corp corp = Corp.findAvailableByName(name);
        if (corp != null) {
            Logger.info("LOG83613: 已经存在" + name + "对应的公司");
            return corp;
        }

        // 生成公司.
        corp = CorpFacade.createWithApp(name, validDays);
        corp.deleted = models.constants.DeletedStatus.UN_DELETED;
        corp.expiredAt = DateHelper.afterDays(validDays);
        corp.licenseEdition = LicenseEdition.TRIAL;
        corp.save();
        return corp;
    }


    /**
     * 检查公司license.
     */
    public static PageResult processLicenseCheck(Corp corp) {

        //Logger.info("LOG04410: Http.Request.current().controller=" + Http.Request.current().controller);
        if ("manager.Orders".equals(Http.Request.current().controller)
                || "api.v20.OrdersAPI".equals(Http.Request.current().controller)
                ) {
            return PageResult.SUCCESS;
        }

        if (corp == null) {
            return PageResult.FORBIDDEN;
        }

        // 不是API才发提示信息
        boolean isApi = Http.Request.current().path.contains("api");

        if (corp.getCurrentLicenseEdition() == LicenseEdition.FREE) { //过期或免费
            // 缓存一下检查
            if (isOutOfFreeLicense(corp)) {
                // 检查人数?
                Long userCount = AdminUser.countValidUserForCorp(corp);
                if (userCount > GlobalConfig.MAX_FREE_USERCOUNT) {
                    if (!isApi) {
                        Scope.Flash.current().put("warn", "当前激活员工数(" + userCount + "人)超过免费版许可("
                                + GlobalConfig.MAX_FREE_USERCOUNT + "人), 不能进行任何修改数据的操作, 请购买新的License");
                    }
                    if (!Http.Request.current().method.equalsIgnoreCase("GET")) {
                        Scope.Flash.current().put("warn", "当前激活员工数(" + userCount + "人)超过免费版许可("
                                + GlobalConfig.MAX_FREE_USERCOUNT + "人), 不能进行任何修改数据的操作, 请购买新的License");
                        return PageResult.BACK;
                    }
                }
            }

        } else if (isOutOfLicense(corp)) {
            // 检查过期
            Logger.info("LOG02600: isOutOfLicense request.method=" + Http.Request.current().method);
            if (!Http.Request.current().method.equalsIgnoreCase("GET")) {
                if (!isApi) {
                    Scope.Flash.current().put("warn", "使用已经到期, 不能进行任何修改数据的操作, 请联系管理员或在线支持");
                }
                return PageResult.BACK;
            } else if (!Scope.Flash.current().contains("warn")) {
                if (!isApi) {
                    Scope.Flash.current().put("warn", "使用已经到期, 请联系管理员或在线支持");
                }
            }
        }
        return PageResult.SUCCESS;
    }


    public static Boolean isOutOfFreeLicense(Corp corp) {
        return CacheHelper.getCache(CacheHelper.getCacheKey(getCacheCorp(corp), "LicenseFree"), "1h", () -> {
            //TODO: 授权检查
            return Boolean.FALSE;
        });
    }

    public static Boolean isOutOfLicense(Corp corp) {
        return corp.isExpired() || CacheHelper.getCache(CacheHelper.getCacheKey(getCacheCorp(corp), "LicenseEdition"), "1h", () -> {
            //TODO: 授权检查
            return Boolean.FALSE;
        });
    }

    public static void clearCorpCache(Corp corp) {
        CacheHelper.delete(getCacheCorp(corp));
    }


    /**
     * Cache Key Corp
     * 公司级缓存统一使用.
     */
    public static String getCacheCorp(Corp corp) {
        return getCacheCorpId(BeanHelper.getModelId(corp));
    }

    public static String getCacheCorpId(String corpId) {
        return "CorpBaseV1_" + corpId;
    }

    /**
     * 是否合法的邮箱后缀.
     */
    public static boolean isValidEmailPostfix(Corp corp, String email) {
        Logger.info("LOG04690: corp.emailPostfix=" + corp.emailPostfix);
        if (StringUtils.isBlank(corp.emailPostfix)) {
            return true;
        }
        String[] splitEmailPostfixs = corp.emailPostfix.toLowerCase().split("[\\s;；，,]+");
        String lowerCaseEmail = email.toLowerCase();
        for (String splitEmailPostfix : splitEmailPostfixs) {
            splitEmailPostfix = splitEmailPostfix.replaceAll("@", "");
            Logger.info("LOG04720: splitEmailPostfix=%s", splitEmailPostfix);
            if (lowerCaseEmail.endsWith("@" + splitEmailPostfix)) {
                return true;
            }
        }
        return false;
    }

    public static String getValidEmailPostfixMessage(Corp corp) {
        Logger.info("LOG04690: corp.emailPostfix=" + corp.emailPostfix);
        if (StringUtils.isBlank(corp.emailPostfix)) {
            return "";
        }
        String[] splitEmailPostfixs = corp.emailPostfix.toLowerCase().split("[\\s;；，,]+");

        String result = Arrays.asList(splitEmailPostfixs).stream().filter(StringUtils::isNotBlank).map(s -> "@" + s).collect(Collectors.joining("或"));

        return "邮箱必须是以" + result + "结尾的公司邮箱";
    }


    public static List<String> getCorpFuncs(Corp corp) {
        if (corp == null) {
            return Collections.emptyList();
        }

        List<String> funcs = new ArrayList<>();
        for (Func func : corp.getCorpFuncSet()) {
            funcs.add(func.toString());
        }
        return funcs;
    }

    private static Corp createCorpForLicense(String name) {
        Corp corp = new Corp();
        corp.name = name;
        corp.createdAt = new Date();
        corp.enabled = Boolean.TRUE;

        updateCorpWithLicense(corp);

        return corp;
    }


    /**
     * 本方法只有安装版本都会执行.
     */
    private static void updateCorpWithLicense(Corp corp) {
        if (!isPrivateInstallVersion()) {
            Logger.info("LOG04223: 在线版");
            return;
        }
        corp.licenseEdition = LicenseEdition.BASIC;  // 默认是试用版
        corp.updatedAt = new Date();
        corp.enabled = Boolean.TRUE;
        corp.deleted=models.constants.DeletedStatus.UN_DELETED;

        if (Play.mode.isProd()) {
            if (StringUtils.isBlank(GlobalConfig.CORP_EXPIRE_ON)) {
                Logger.info("LOG838113: 没有指定有效期，立即退出");
                Play.fatalServerErrorOccurred();
            }
            corp.expiredAt = DateUtil.getEndOfDay(DateHelper.t(GlobalConfig.CORP_EXPIRE_ON));
            corp.licenseEdition = EnumUtils.getEnum(LicenseEdition.class, GlobalConfig.LICENSE_TYPE);
            if (corp.licenseEdition == null) {
                corp.licenseEdition = LicenseEdition.BASIC; // 安装版 使用企业版
            }
        } else {
            corp.expiredAt = DateUtil.getEndOfDay(DateHelper.afterDays(365));
        }

        if (StringUtils.isNotBlank(GlobalConfig.LICENSE_FUNC_LIST)) {
            corp.additionFuncs = GlobalConfig.LICENSE_FUNC_LIST;
        }
        if (StringUtils.isNotBlank(GlobalConfig.LICENSE_FUNC_REMOVE)) {
            // 设置公司级禁用的功能.
            corp.disabledFuncs = GlobalConfig.LICENSE_FUNC_REMOVE;
        }

        if (StringUtils.isNotBlank(GlobalConfig.LICENSE_ROLES_DISABLED)) {
            // 设置公司级禁用的角色.
            corp.disabledRoles = GlobalConfig.LICENSE_ROLES_DISABLED;
        }

        corp.save();
        Logger.info("LOG04353: after updateCorpWithLicense corp = " + corp);
    }

    /**
     * 是私有安装版.
     */
    public static boolean isPrivateInstallVersion() {
        return StringUtils.isNotBlank(GlobalConfig.LICENSE_SIGN);
    }

    /**
     * 是私有安装版, 同时有指定Func.
     */
    public static boolean isPrivateInstallAndHasFunc(Func func) {
        if (isPrivateInstallVersion()) {
            Corp corp = Corp.findFirst();
            return corp != null && corp.hasFunc(func);
        }
        return false;
    }

    /**
     * 找到私有安装版本的集团公司.
     * @return
     */
    public static Corp getPrivateInstallRootCorp() {
        if (CorpFacade.isPrivateInstallVersion() && StringUtils.isNotBlank(GlobalConfig.ROOT_CORP_NAME)) {
            return Corp.findAvailableByName(GlobalConfig.ROOT_CORP_NAME);
        }
        return Corp.findFirst();
    }

    /**
     * 从配置文件生成公司信息.
     * <p>
     * 公司由  公司名|upstreamId 组成
     * 多公司用$$分隔
     * <p>
     * 需要支持单个公司. 只在安装版本可用
     */
    public static List<Corp> createByName(String corpNames) {
        List<Corp> corps = new ArrayList<>();
        String[] aryCorpName = corpNames.split("\\$\\$");

        for (String corpNamePair : aryCorpName) {
            String[] corpNodes = corpNamePair.split("\\|");

            String corpName = corpNodes[0];
            Logger.info("TLQ00980: corpName = " + corpName);

            Corp corp = Corp.findByName(corpName);
            if (corp != null) {
                Logger.info("LOG81593: 已经存在" + corpName + "对应的公司:" + corp);
                updateCorpWithLicense(corp);
                corps.add(corp);
            } else {
                corp = createCorpForLicense(corpName);
                if (corpNodes.length > 1) {
                    corp.upstreamId = corpNodes[1];
                    Logger.info("TLQ00990: corpNodes = " + corpNodes[1]);
                }
                corp.save();
                corps.add(corp);
            }
            Logger.info("TLQ30991: corp = " + corp);
        }
        // 指定一个公司作为集团公司
        if (StringUtils.isNotBlank(GlobalConfig.ROOT_CORP_NAME) && CorpFacade.isPrivateInstallVersion()) {
            Corp rootCorp = Corp.findAvailableByName(GlobalConfig.ROOT_CORP_NAME);
            if (rootCorp != null) {
                Logger.info("LOG06193: 找到集团公司：" + rootCorp);
                for (Corp corp : corps) {
                    if (!rootCorp.id.equals(corp.id)) {
                        corp.rootCorpId = rootCorp.id;
                        corp.save();
                    }
                }
            }
        }


        return corps;
    }

    /**
     * 得到公司名列表, 用于检查是否是合法的公司名.
     * for LicenseChecker， 不要删除
     */
    public static Set<String> getCorpNameSet(String corpNames) {
        Set<String> corpNameSet = new HashSet<>();
        String[] aryCorpName = corpNames.split("\\$\\$");
        for (String corpNamePair : aryCorpName) {
            String[] corpNodes = corpNamePair.split("\\|");
            String corpName = corpNodes[0];
            Logger.info("TLQ00981: corpName = " + corpName);
            corpNameSet.add(corpName);
        }

        return corpNameSet;
    }

    /**
     * 用于构造公司GlobalConfig的renderArgs.
     */
    public static void setupCorpGlobalConfigsRenderArgs(Corp corp, String config) {
        List<EntityProp> entityProps = EntityProp.findAllByEntityId(corp.id);

        Set<String> staticFieldSet = GlobalConfigKeys.getStaticFieldSet();
        List<KeyMessage> allConfigs = staticFieldSet.stream()
                .sorted()
                .map(key -> new KeyMessage(key, Play.configuration.getProperty(key)))
                .collect(Collectors.toList());

        if (entityProps != null && config == null) {
            config = entityProps.stream()
                    .filter(entityProp -> staticFieldSet.contains(entityProp.key) && entityProp.value != null)
                    .map(entityProp -> entityProp.key + "=" + entityProp.value)
                    .sorted()
                    .collect(Collectors.joining("\r"));
        }
        Scope.RenderArgs.current().put("entityProps", entityProps);
        Scope.RenderArgs.current().put("allConfigs", allConfigs);
        Scope.RenderArgs.current().put("config", config);
    }

    /**
     * 保存文本形式的公司级别配置.
     */
    public static void saveCorpGlobalConfigs(Corp corp, @Valid @Required String config) {
        String[] lines = config.split("\\r?\\n|\\r");
        Set<String> staticFieldSet = new HashSet<>();
        staticFieldSet.addAll(GlobalConfigKeys.getStaticFieldSet());
        for (String line : lines) {
            String[] values = StringUtils.split(line, "=");
            if (values.length > 1) {
                String key = values[0].trim();
                if (staticFieldSet.contains(key)) {
                    EntityProp.setKeyValue(corp.id, key, values[1].trim());
                    staticFieldSet.remove(key);
                }
            }
        }
        for (String key : staticFieldSet) {
            EntityProp.cleanKey(corp.id, key);
        }
        CorpFacade.clearCorpCache(corp);
        Scope.Flash.current().put("notice", "配置保存成功");
    }

    public static String getCorpBindPlatformName(Corp corp) {
        String clientName = "微信";
        if (corp != null && corp.bindPlatform() == OpenIdSource.DING) {
            return "钉钉";
        }
        return clientName;
    }

    public static CorpResponse getCorpResponse(Corp corp, AdminUser user) {
        //user.status = UserStatus.ACTIVE;//TODO 状态已更改 不再是UserStatus
        CorpResponse corpResponse = CorpResponse.fullFromWithExtInfo(corp);

        addAbility(corpResponse, corp);

        return corpResponse;
    }

    public static void addAbility(CorpResponse corpResponse, Corp corp) {

    }

}
